home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Utilities / GOCR / src / pnm.cc < prev    next >
C/C++ Source or Header  |  2000-05-29  |  7KB  |  216 lines

  1. #include <stdio.h>
  2. // #include <stdlib.h>
  3. // #include <assert.h>
  4.  
  5. #include "pnm.h"
  6.  
  7. #define EE()         fprintf(stderr,"\nERROR "__FILE__" L%d: ",__LINE__)
  8. #define E0(x0)       {EE();fprintf(stderr,x0 "\n");      }
  9. #define F0(x0)       {EE();fprintf(stderr,x0 "\n");      exit(1);}
  10. #define F1(x0,x1)    {EE();fprintf(stderr,x0 "\n",x1);   exit(1);}
  11. #define F2(x0,x1,x2) {EE();fprintf(stderr,x0 "\n",x1,x2);exit(1);}
  12.  
  13. // --- needed for reading PNM-files
  14. int spc(char c){ return ((c==' '  || c=='\t'
  15.                        || c=='\r' || c=='\n') ? 1 : 0 ); }
  16. int num(char c){ return ((c>='0'  && c<='9' ) ? 1 : 0 ); }
  17.  
  18. char read_char(FILE *f1){    // filter #-comments
  19.   char c; int  m;
  20.   for(m=0;;){
  21.     c=fgetc(f1);
  22.     if( feof(f1)   ) E0("read feof");
  23.     if( ferror(f1) ) F0("read ferror");
  24.     if( c=='#'  ) { m=1; continue; }
  25.     if( m==0    ) return c;
  26.     if( c=='\n' ) m=0;
  27.   }
  28. }
  29.  
  30. void readpgm(char *name,pix *p,int vvv){    // raw-ppm
  31.   char c1,c2;          int nx,ny,nc,mod,i,j,k;    // buffer
  32.   FILE *f1;            unsigned char *pic;
  33.  
  34.   if(name[0]=='-' && name[1]==0){
  35.     f1=stdin;  /* is this correct ??? */
  36.   } else {
  37.     f1=fopen(name,"rb"); if(!f1)F1("opening file %s",name);
  38.   }
  39.   c1=fgetc(f1); if(feof(f1))F0("read");
  40.   c2=fgetc(f1); if(feof(f1))F0("read");
  41.   if(c1!='P')F0("first byte should be P in PNM-files");
  42.   if(c2!='5' && c2!='4' && c2!='6')// F0("no PNM-RAW"); // PGM-RAW,PBM-RAW,PPM-RAW
  43.   if(c2!='1' && c2!='2' && c2!='3')F0("no PNM");
  44.   nx=ny=nc=0; if( c2=='4' || c2=='1') nc=1;
  45.   for(mod=0;((c2=='5' || c2=='2') && (mod&7)<6)
  46.         ||  ((c2=='6' || c2=='3') && (mod&7)<6)        
  47.         ||  ((c2=='4' || c2=='1') && (mod&7)<4);)        
  48.   {                        // mode: 0,2,4=[ |\t|\r|\n] 
  49.                           //   1=nx 3=ny 5=nc 8-13=#rem
  50.     c1=read_char(f1);                // frueher: # mod|=8
  51.     if( (mod & 1)==0 )                // whitespaces
  52.     if( !spc(c1) ) mod++;
  53.     if( (mod & 1)==1 )
  54.     if( !num(c1) ) {
  55.       if( !spc(c1) )F0("unexpected character");
  56.       mod++; }
  57.     else if(mod==1) nx=nx*10+c1-'0';
  58.     else if(mod==3) ny=ny*10+c1-'0';
  59.     else if(mod==5) nc=nc*10+c1-'0';
  60.   }
  61.   if(nc>=256)F0("nc >= 256"); // realy RAW?
  62.   if(vvv)
  63.   printf("# PNM P%c x=%d y=%d c=%d head=%ld",c2,nx,ny,nc,ftell(f1));
  64.   if( c2=='4' && (nx&7)!=0 ){
  65.     /* nx=(nx+7)&~7;*/ if(vvv)printf(" PBM2PGM nx %d",(nx+7)&~7);
  66.   }
  67.   fflush(stdout);
  68.   // pic=new Uchar[ (*nx)*(*ny) ];        // errors!
  69.   pic=new unsigned char[ nx*ny*((c2=='6')?3:1) ];
  70.   if(pic==NULL)F0("memory failed");                // no memory
  71.   if( c2=='5' )
  72.     if(ny!=(int)fread(pic,   nx,ny,f1))F0("read");    // read all lines
  73.   if( c2=='2' )for(mod=j=i=0;i<nx*ny && !feof(f1);){        // not very clever
  74.     c1=read_char(f1);
  75.     if( !num(c1) ) {  if( !spc(c1) )F0("unexpected char");
  76.       if(1&mod) { pic[i]=j*255/nc; i++; j=0; mod=0; }  }
  77.     else { j=j*10+c1-'0'; mod=1; };
  78.   }
  79.   if( c2=='1' )for(mod=j=i=0,nc=255;i<nx*ny && !feof(f1);){    // PBM-ASCII 0001100
  80.     c1=read_char(f1);
  81.     if( num(c1) ) { pic[i]=((c1=='0')?255:0); i++; }
  82.     else if( !spc(c1) )F0("unexpected char");
  83.   }
  84.   if( c2=='3' )for(mod=k=j=i=0;i<nx*ny*3 && !feof(f1);){
  85.     c1=read_char(f1);
  86.     if( !num(c1) ) {  if( !spc(c1) )F0("unexpected char");
  87.       if(1&mod) { k+=j; if(mod==5){ pic[i]=k/3; i++; }
  88.         j=0; mod=(mod+1)%6; }  }
  89.     else { j=j*10+c1-'0'; if(!(mod&1)) mod++; };
  90.   }
  91.   if( c2=='6' ){
  92.     if(ny!=(int)fread(pic, 3*nx,ny,f1))F0("read");    // read all lines
  93.     int lx,ly;
  94.     for(ly=0;ly<ny;ly++)
  95.     for(lx=0;lx<nx;lx++)
  96.     pic[lx+ly*nx]=( pic[0+3*lx+3*ly*nx]
  97.                    +pic[1+3*lx+3*ly*nx]
  98.                    +pic[2+3*lx+3*ly*nx] ) / 3;
  99.   }
  100.   if( c2=='4' ){                // PBM-RAW
  101.     int dx=(nx+7)&~7;                // dx (mod 8)
  102.     if(ny!=(int)fread(pic,dx>>3,ny,f1))F0("read");    // read all bytes
  103.     int lx,ly;
  104.     for(ly=ny-1;ly>=0;ly--)
  105.     for(lx=nx-1;lx>=0;lx--)
  106.     pic[lx+ly*nx]=( (128 & pic[(lx+ly*dx)>>3]<<(lx & 7)) ? 0 : 255 );
  107. #if 0
  108.     // using gray values for fuzzy logic
  109.     for(ly=ny-2;ly>0;ly--)
  110.     for(lx=nx-2;lx>0;lx--){                // takes time!
  111.       pic[lx+ly*nx]=
  112.             ((pic[ lx   + ly   *nx]>128)?192:64)    // reduce contrast
  113.            +((pic[(lx+1)+(ly  )*nx]>128)?  8:-8)    // max 4*8+4*4=48;
  114.            +((pic[(lx-1)+(ly  )*nx]>128)?  8:-8)
  115.            +((pic[(lx  )+(ly+1)*nx]>128)?  8:-8)
  116.            +((pic[(lx  )+(ly-1)*nx]>128)?  8:-8)
  117.            +((pic[(lx+1)+(ly+1)*nx]>128)?  4:-4)
  118.            +((pic[(lx-1)+(ly+1)*nx]>128)?  4:-4)
  119.            +((pic[(lx+1)+(ly-1)*nx]>128)?  4:-4)
  120.            +((pic[(lx-1)+(ly-1)*nx]>128)?  4:-4);
  121.     }
  122. #endif
  123.     nc=255;
  124.   }
  125.   if(name[0]=='-' && name[1]==0){
  126.     f1=NULL;
  127.   } else {
  128.     fclose(f1);
  129.   }
  130.   p->p=pic;  p->x=nx;  p->y=ny; p->bpp=1;
  131.   if(vvv)printf("\n");
  132. }
  133.  
  134. int writepgm(char *nam,pix p){// P5 raw-pgm
  135.   FILE *f1;int a,x,y;
  136.   f1=fopen(nam,"wb");if(!f1)F0("open");        // open-error
  137.   fprintf(f1,"P5\n%d %d\n255\n",p.x,p.y);
  138.   if(p.bpp==3)
  139.   for(y=0;y<p.y;y++)
  140.   for(x=0;x<p.x;x++){    // set bit
  141.     a=x+y*p.x;
  142.     p.p[a]=(p.p[3*a+0]+p.p[3*a+1]+p.p[3*a+2])/3;
  143.   }
  144.   if(p.y!=(int)fwrite(p.p,p.x,p.y,f1))F0("write");    // write all lines
  145.   fclose(f1);
  146.   return 0;
  147. }
  148.  
  149. // pgm2ppm, use last 3 bits for farbcoding 
  150. int writeppm(char *nam,pix p){// P6 raw-ppm
  151.   FILE *f1;int x,y; unsigned char rgb[3];
  152.   f1=fopen(nam,"wb");if(!f1)F0("open");        // open-error
  153.   fprintf(f1,"P6\n%d %d\n255\n",p.x,p.y);
  154.   if( p.bpp==1 )
  155.   for(y=0;y<p.y;y++)
  156.   for(x=0;x<p.x;x++){
  157.     rgb[0]=rgb[1]=rgb[2]=p.p[x+y*p.x];
  158.     if(p.p[x+y*p.x]&4) rgb[0]=64;
  159.     if(p.p[x+y*p.x]&2) rgb[1]=64;
  160.     if(p.p[x+y*p.x]&1) rgb[2]=64;
  161.     if( 1!=(int)fwrite(rgb,3,1,f1) )F0("write");
  162.   }
  163.   if( p.bpp==3 )
  164.   if( p.y!=(int)fwrite(p.p,3*p.x,p.y,f1) )F0("write");
  165.   fclose(f1);
  166.   return 0;
  167. }
  168.  
  169. // high bit = first, 
  170. int writepbm(char *nam,pix p){// P4 raw-pbm
  171.   FILE *f1;int x,y,a,b,dx,i;
  172.   dx=(p.x+7)&~7;    // enlarge to a factor of 8
  173.   for(y=0;y<p.y;y++)
  174.   for(x=0;x<p.x;x++){    // set bit
  175.     a=(x+y*dx)>>3;b=7-(x&7);    // adress an bitnumber
  176.     i=x+y*p.x;
  177.     if(p.bpp==3) i=(p.p[3*i+0]+p.p[3*i+1]+p.p[3*i+2])/3;
  178.     else         i= p.p[  i  ];
  179.     i=((i>127)?0:1);
  180.     p.p[a]=(p.p[a] & (~1<<b)) | i<<b;
  181.   }
  182.   f1=fopen(nam,"wb");if(!f1)F0("open");        // open-error
  183.   fprintf(f1,"P4\n%d %d\n",p.x,p.y);
  184.   if(p.y!=(int)fwrite(p.p,dx>>3,p.y,f1))F0("write");    // write all lines
  185.   fclose(f1);
  186.   return 0;
  187. }
  188. // ------------------------------------------------------------------------
  189.  
  190. // ----- count colors ------ create histogram -------
  191. void makehisto(pix p, unsigned col[256], int vvv){
  192.   int i,j,x,y;
  193.   for(i=0;i<256;i++) col[i]=0;
  194.   for(x=0;x<p.x;x++)
  195.   for(y=0;y<p.y;y++) col[ p.p[x+p.x*y] ]++;
  196.   for(i=255;i>  0;i--) if( col[i] ) break;    // brightest pixel
  197.   for(j=  0;j<255;j++) if( col[j] ) break;    // darkest
  198.   if(i  <64) printf("Warning: max intensity=%d<64, too dark\n",i);
  199.   if(i-j<64) printf("Warning: contrast=(%d-%d)<64\n",i,j);
  200.   if(i-j<=8)F0("to less contrast ???");
  201.   /* smoothen */
  202.   for(j=8;j>0;j--)for(i=0;i<255-j;i++){
  203.     x=col[i];y=col[i+1];col[i]=(3*x+y)/4;col[i+1]=(x+3*y)/4;
  204.   }
  205.   /* how to detect main maximas? */
  206.   if(vvv){
  207.     printf("#!gnuplot\n"
  208.            " set data style lines\n"
  209.            " plot \"-\"\n");
  210.     for(i=0;i<256;i++) 
  211.     printf(" %8d %8d\n",i,col[i]);
  212.     printf("e\npause -1\n");
  213.   }
  214. }
  215.  
  216.